import dayjs, { Dayjs } from 'dayjs'
import { v1 as uuidV1 } from 'uuid'
import is from '@/utils/is'
import emojiRegex from 'emoji-regex'
import shortid from 'shortid'
import { isNil, last, random } from 'lodash-es'
import type { Rule } from 'ant-design-vue/es/form'

export function getUUid() {
  // @ts-ignore
  return `${uuidV1(Date.now())}-${random(10000, 99999)}`
}

export function formatDate(date: string | Dayjs, formatter = 'YYYY-MM-DD HH:mm:ss') {
  if (!date) {
    return date
  }
  return dayjs(date).format(formatter)
}

export function toLabelValue<T extends { [key: string | number]: unknown }, K extends keyof T>(
  data: T,
  toNumber = true
) {
  return Object.keys(data).reduce<{ label: T[K]; value: K }[]>((p, k) => {
    p.push({
      label: data[k],
      // @ts-ignore-next-line
      value: toNumber ? Number(k) : k
    })
    return p
  }, [])
}

export const checkNumber = (errMsg: string[]) => (_rule: Rule, value: number) => {
  if (!value) {
    return Promise.reject(errMsg[0])
  }
  if (!is.number(value)) {
    return Promise.reject(errMsg[1])
  }
  return Promise.resolve()
}

export function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve) => {
    const fileReader = new FileReader()
    fileReader.readAsDataURL(file)
    fileReader.onload = function () {
      resolve(this.result as string)
    }
  })
}

export function base64ToFile(base64: string, filename: string) {
  // 获取到base64编码
  const arr = base64.split(',')
  // 将base64编码转为字符串
  const str = window.atob(arr[1])
  let n = str.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = str.charCodeAt(n)
  }
  return new File([u8arr], filename, {
    type: 'image/png'
  })
}

export function picSrcToBase64(src: string): Promise<string> {
  return new Promise((resolve) => {
    const img = new Image()
    img.src = src
    img.crossOrigin = 'Anonymous'
    img.onload = function () {
      resolve(imgToCanvas(img))
    }
    img.onerror = function () {
      resolve('')
    }
  })
}

function imgToCanvas(img: HTMLImageElement) {
  try {
    const canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height

    const ctx = canvas.getContext('2d')
    ctx!.drawImage(img, 0, 0)
    const base64 = canvas.toDataURL('image/png')
    canvas.remove()

    return base64.split(',')[1]
  } catch (e) {
    console.log(e)
    return ''
  }
}

export function setBase64Prefix(base64: string) {
  console.log(`data:image/png;base64,${base64}`, '图片加载加密', base64)

  return `data:image/png;base64,${base64}`
}

export function getMime(picName: string) {
  return last(picName.split('.'))
}

export function makeShortId() {
  shortid.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$¥')
  return shortid.generate()
}

export function emojiMatcher(text: string) {
  let result: string | undefined
  const regex = emojiRegex()
  for (const match of text.matchAll(regex)) {
    result = match[0]
  }
  return !isNil(result)
}

export function containsBraces(str: string) {
  const regex = /\{.*\}/g
  return regex.test(str)
}

export function byteLength(str: string) {
  //获取字符串的字节数
  let b = 0
  const l = str.length //初始化字节数递加变量并获取字符串参数的字符个数
  if (l) {
    //如果存在字符串，则执行计划
    for (let i = 0; i < l; i++) {
      //遍历字符串，枚举每个字符
      if (str.charCodeAt(i) > 255) {
        //字符编码大于255，说明是双字节字符
        b += 2 //则累加2个
      } else {
        b++ //否则递加一次
      }
    }
    return b //返回字节数
  } else {
    return 0 //如果参数为空，则返回0个
  }
}

export function byteLengthSplit(str: string, point = 80) {
  const splitStr = ['', '']
  let str1Lock = false
  for (let i = 0; i < str.length; i++) {
    if (str1Lock) {
      if (byteLength(splitStr[1]) + byteLength(str[i]) <= point) {
        splitStr[1] += str[i]
      }
    } else {
      if (byteLength(splitStr[0]) + byteLength(str[i]) <= point) {
        splitStr[0] += str[i]
      } else {
        splitStr[1] += str[i]
        str1Lock = true
      }
    }
  }

  return splitStr
}

export function validParentheses(s: string) {
  const stack = []
  let res = 0
  for (let i = 0; i < s.length; i++) {
    if (s[i] === '{') {
      if (stack.length > 0 && stack[stack.length - 1].value === '{') {
        return false
      }
      stack.push({
        value: s[i],
        index: i
      })
      res++
    } else if (s[i] === '}') {
      const token = stack[stack.length - 1]
      if (token?.value === '{') {
        if (i - token?.index <= 1) {
          return false
        }
        stack.pop()
        if (stack.length > 0) {
          return false
        }
        res--
      } else {
        return false
      }
    }
  }
  return res === 0
}

export const serializer = {
  read: (v: any) => (v ? JSON.parse(v) : null),
  write: (v: any) => JSON.stringify(v)
}
